/**
 * Copyright (C) 2007-2011 JUG Events Team <info@jugevents.org>
 *
 * This file is part of JUG Events Web Application.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package it.jugpadova.blo;

import it.jugpadova.controllers.EventEditController;
import it.jugpadova.dao.SpeakerDao;
import it.jugpadova.po.Event;
import it.jugpadova.po.Speaker;

import java.util.List;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.util.Version;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.directwebremoting.proxy.dwr.Util;
import org.directwebremoting.proxy.scriptaculous.Effect;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.lambico.dao.spring.hibernate.HibernateGenericDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * BO for Speaker entity.
 *
 */
@Component
@RemoteProxy(name = "speakerBo")
public class SpeakerBo {

    private static final Logger logger = Logger.getLogger(SpeakerBo.class);
    @Autowired
    private SpeakerDao speakerDao;

    /**
     * Execute a full text search on speakers. Hardly copied from the corresponding
     * search in EventBo.
     * @param searchQuery
     * @param maxResults
     * @return
     * @throws ParseException
     */
    public List<Speaker> search(String searchQuery, int maxResults) throws ParseException {
        List<Speaker> result = null;
        Session session =
                ((HibernateGenericDao) speakerDao).getHibernateTemplate().
                getSessionFactory().getCurrentSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);
        MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30,
                new String[]{"firstName", "lastName", "resume"},
                new StandardAnalyzer(Version.LUCENE_30));
        org.apache.lucene.search.Query query = parser.parse(searchQuery);
        FullTextQuery hibQuery =
                fullTextSession.createFullTextQuery(query, Speaker.class);
        //  hibQuery.setSort(arg0)      
        if (maxResults > 0) {
            hibQuery.setMaxResults(maxResults);
        }
        // hibQuery.enableFullTextFilter("onlyMyJUG");
        result = hibQuery.list();
        return result;
    }
    
    public void regenerateLuceneIndexes() {
        Session session =
                ((HibernateGenericDao) speakerDao).getHibernateTemplate().
                getSessionFactory().getCurrentSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);
        fullTextSession.getTransaction().begin();
        fullTextSession.setFlushMode(FlushMode.MANUAL);
        fullTextSession.setCacheMode(CacheMode.IGNORE);
        ScrollableResults results = fullTextSession.createCriteria(Speaker.class).
                scroll(ScrollMode.FORWARD_ONLY);

        int index = 0;
        while (results.next()) {
            index++;
            fullTextSession.index(results.get(0)); //index each element

//            if (index % 50 == 0) {
//                fullTextSession.clear(); //clear every batchSize since the queue is processed
//
//            }
        }
        fullTextSession.getTransaction().commit();
        session.disconnect();        
    }

    @RemoteMethod
    public void fullTextSearch(String searchQuery, int maxResults) {
        if (StringUtils.isNotBlank(searchQuery)) {
            WebContext wctx = WebContextFactory.get();
            ScriptSession session = wctx.getScriptSession();
            Util util = new Util(session);
            List<Speaker> speakers = null;
            try {
                speakers = this.search(searchQuery, maxResults);
            } catch (ParseException pex) {
                logger.info("Error parsing query: " + searchQuery);
            } catch (Exception ex) {
                logger.error("Error searching speakers", ex);
            }
            if (speakers != null && speakers.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (Speaker speaker : speakers) {
                    Event event = speaker.getEvent();
                    sb.append("<div>\n");
                    sb.append("<div class=\"eventDate\">").append(speaker.getFirstName()).append(" ").
                            append(speaker.getLastName()).append("</div>").append("<br/>");
                    sb.append(event.getTitle()).append("&nbsp;(").append(event.getOwner().getJug().
                            getName()).append(")<br/>");
                    sb.append("&nbsp;<a href=\"javascript:populateSpeakerFields(\'").append(speaker.
                            getId()).append("\');\">Select this speaker</a>").append("<br/>");
                    sb.append("</div>\n").append("<br/>");
                }
                util.setValue("content_textSearch_result", sb.toString(), false);
            } else {
                util.setValue("content_textSearch_result", "", false);
            }
        }
    }

    @RemoteMethod
    public void populateSpeakerFields(String speakerId) {
        Speaker speaker = speakerDao.get(new Long(speakerId));
        if (speaker != null) {

            WebContext wctx = WebContextFactory.get();
            HttpSession httpSession = wctx.getSession();
            Speaker sessionSpeaker = (Speaker) httpSession.getAttribute(
                    EventEditController.SESSION_SPEAKER);
            if (sessionSpeaker != null) {
                sessionSpeaker.setPicture(speaker.getPicture());
            }
            ScriptSession session = wctx.getScriptSession();
            Util util = new Util(session);
            String cp = wctx.getHttpServletRequest().getContextPath();
            util.setValue("firstName", speaker.getFirstName());
            util.setValue("lastName", speaker.getLastName());
            util.setValue("email", speaker.getEmail());
            util.setValue("resume", speaker.getResume());
            util.setValue("url", speaker.getUrl());
            util.setValue("skypeId", speaker.getSkypeId());
            util.setValue("speakerImage",
                    "<img style=\"float: right;\" src=\"" + cp + "/bin/pictureSpeaker.bin?id=" + speaker.
                    getId() + "\" alt=\"Speaker Image\" width=\"100\"/>");
            //some effects...
            Effect effect = new Effect(session);
            effect.highlight("firstName");
            effect.highlight("lastName");
            effect.highlight("email");
            effect.highlight("resume");
            effect.highlight("url");
            effect.highlight("skypeId");

        }

    }
}
